﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;
using System.IdentityModel.Tokens.Jwt;

namespace FlyingEye.SignalRHubs
{
    /// <summary>
    /// 监视服务中心
    /// </summary>
    [Authorize]
    public class MonitorServiceHub : Hub<IMessageDispatcherClient>
    {
        private readonly ILogger<MonitorServiceHub> _logger;

        private readonly SignalRClientMapping _clientMapping;

        private readonly SignalRGroupMapping _groupMapping;

        public MonitorServiceHub(
            ILogger<MonitorServiceHub> logger,
            SignalRClientMapping clientMapping,
            SignalRGroupMapping groupMapping)
        {
            _logger = logger;
            _clientMapping = clientMapping;
            _groupMapping = groupMapping;
        }

        public async override Task OnConnectedAsync()
        {
            var httpContext = this.Context.GetHttpContext();

            if (httpContext != null)
            {
                if (httpContext.Request.Headers.TryGetValue("Authorization", out var tokenFromHeader))
                {
                    var token = tokenFromHeader.ToString().Remove(0, "Bearer ".Length);
                    JwtSecurityTokenHandler jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
                    var jwtSecurityToken = jwtSecurityTokenHandler.ReadJwtToken(token);

                    if (jwtSecurityToken.Payload.TryGetValue("signalr_connection_type", out var connectionType)
                        && jwtSecurityToken.Payload.TryGetValue("signalr_connection_name", out var connectionName))
                    {
                        var connectionTypeString = connectionType.ToString();
                        var connectionNameString = connectionName.ToString();

                        if (!string.IsNullOrWhiteSpace(connectionTypeString)
                            && !string.IsNullOrWhiteSpace(connectionNameString))
                        {
                            if (connectionTypeString == "client")
                            {
                                // 如果连接是客户端连接，则将连接添加到客户端映射中
                                if (_clientMapping.TryAdd(connectionNameString, Context.ConnectionId))
                                {
                                    _logger.LogInformation($"客户端 {connectionNameString} 已连接！");
                                }
                            }
                            else
                            if (connectionTypeString == "group")
                            {
                                if (_groupMapping.TryAdd(connectionNameString, Context.ConnectionId))
                                {
                                    // 如果连接是组连接，则将连接添加到组中
                                    await this.Groups.AddToGroupAsync(Context.ConnectionId, connectionNameString);
                                    _logger.LogInformation($"客户端 {Context.ConnectionId} 已连接到组 {connectionNameString} ！");
                                }
                            }
                            else
                            {
                                _logger.LogWarning($"未知的连接类型: {connectionTypeString}");
                            }
                        }
                    }
                }
            }

            await base.OnConnectedAsync();
        }

        /// <summary>
        /// 连接断开处理（内存泄漏修复）
        /// </summary>
        public override async Task OnDisconnectedAsync(Exception? exception)
        {
            // 移除连接的客户端或组
            if (!_clientMapping.TryRemoveByConnectionId(Context.ConnectionId, out var clientName))
            {
                if (_groupMapping.TryRemoveByConnectionId(Context.ConnectionId, out var groupName))
                {
                    await this.Groups.RemoveFromGroupAsync(Context.ConnectionId, groupName);
                    _logger.LogInformation($"客户端 {Context.ConnectionId} 已从组 {groupName} 断开连接 ！");
                }
            }
            else
            {
                _logger.LogInformation($"客户端 {clientName} 已断开连接！");
            }

            await base.OnDisconnectedAsync(exception);
        }
    }
}